#include "./BSP/BEEP/beep_music.h"
#include "./SYSTEM/delay/delay.h"
#include <stdio.h>
#include <math.h>

/* -------------------------------------------- 音乐实现函数 -------------------------------------------- */

/**
 * @brief       播放单个音符
 * @param[in]   freq        音符频率 (Hz)
 * @param[in]   duration    持续时间 (毫秒)
 * @retval      无
 * @note        播放指定频率和持续时间的音符
 *              频率为0时播放休止符（静音）
 */
void beep_play_note(float freq, uint16_t duration)
{
    /* 初始化蜂鸣器 */
    beep_init();
    
    if (freq > 0.0f)
    {
        /* 播放音符 */
        beep_set_frequency((uint32_t)freq);
        beep_set_volume(70);  /* 70%音量 */
        beep_start();
        HAL_Delay(duration);
        beep_stop();
    }
    else
    {
        /* 播放休止符（静音） */
        HAL_Delay(duration);
    }
}

/**
 * @brief       播放音符序列
 * @param[in]   notes       音符数组指针
 * @param[in]   count       音符数量
 * @retval      无
 * @note        依次播放音符数组中的所有音符
 */
void beep_play_melody(const music_note_t* notes, uint16_t count)
{
    uint16_t i;
    
    /* 初始化蜂鸣器 */
    beep_init();
    
    /* 依次播放每个音符 */
    for (i = 0; i < count; i++)
    {
        beep_play_note(notes[i].frequency, notes[i].duration);
        
        /* 音符之间的短暂间隔 */
        HAL_Delay(10);
    }
}

/**
 * @brief       播放音乐片段
 * @param[in]   melody      音乐片段指针
 * @retval      无
 * @note        播放完整的音乐片段，包含速度控制
 */
void beep_play_music(const music_melody_t* melody)
{
    uint16_t i;
    uint16_t adjusted_duration;
    
    /* 初始化蜂鸣器 */
    beep_init();
    
    /* 设置音量 */
    beep_set_volume(melody->volume);
    
    /* 依次播放每个音符 */
    for (i = 0; i < melody->note_count; i++)
    {
        /* 根据速度调整持续时间 */
        adjusted_duration = (melody->notes[i].duration * 120) / melody->tempo;
        
        beep_play_note(melody->notes[i].frequency, adjusted_duration);
        
        /* 音符之间的短暂间隔 */
        HAL_Delay(10);
    }
}

/**
 * @brief       计算音符频率
 * @param[in]   octave      八度 (3-7)
 * @param[in]   note        音符 (0-11, 0=C, 1=C#, 2=D, ..., 11=B)
 * @retval      计算得到的频率 (Hz)
 * @note        根据八度和音符计算标准频率
 *              使用十二平均律计算
 */
float beep_calculate_note_freq(uint8_t octave, uint8_t note)
{
    float freq;
    int semitones;
    
    /* 参数检查 */
    if (octave < 3 || octave > 7) octave = 4;
    if (note > 11) note = 0;
    
    /* 计算半音数 */
    semitones = (octave - 4) * 12 + note;
    
    /* 使用十二平均律计算频率 */
    /* 公式: freq = A4 * 2^(semitones/12) */
    freq = A4_STANDARD * powf(2.0f, (float)semitones / 12.0f);
    
    return freq;
}

/**
 * @brief       计算音程频率
 * @param[in]   base_freq   基础频率 (Hz)
 * @param[in]   interval    音程类型
 * @retval      计算得到的频率 (Hz)
 * @note        根据基础频率和音程计算目标频率
 */
float beep_calculate_interval(float base_freq, music_interval_t interval)
{
    float interval_ratio;
    
    /* 根据音程类型确定频率比值 */
    switch (interval)
    {
        case INTERVAL_UNISON:
            interval_ratio = 1.0f;
            break;
        case INTERVAL_MINOR_SECOND_ENUM:
            interval_ratio = 1.05946f;  /* 2^(1/12) */
            break;
        case INTERVAL_MAJOR_SECOND_ENUM:
            interval_ratio = 1.12246f;  /* 2^(2/12) */
            break;
        case INTERVAL_MINOR_THIRD_ENUM:
            interval_ratio = 1.18921f;  /* 2^(3/12) */
            break;
        case INTERVAL_MAJOR_THIRD_ENUM:
            interval_ratio = 1.25992f;  /* 2^(4/12) */
            break;
        case INTERVAL_PERFECT_FOURTH_ENUM:
            interval_ratio = 1.33484f;  /* 2^(5/12) */
            break;
        case INTERVAL_TRITONE_ENUM:
            interval_ratio = 1.41421f;  /* 2^(6/12) */
            break;
        case INTERVAL_PERFECT_FIFTH_ENUM:
            interval_ratio = 1.49831f;  /* 2^(7/12) */
            break;
        case INTERVAL_MINOR_SIXTH_ENUM:
            interval_ratio = 1.58740f;  /* 2^(8/12) */
            break;
        case INTERVAL_MAJOR_SIXTH_ENUM:
            interval_ratio = 1.68179f;  /* 2^(9/12) */
            break;
        case INTERVAL_MINOR_SEVENTH_ENUM:
            interval_ratio = 1.78180f;  /* 2^(10/12) */
            break;
        case INTERVAL_MAJOR_SEVENTH_ENUM:
            interval_ratio = 1.88775f;  /* 2^(11/12) */
            break;
        case INTERVAL_OCTAVE_8VA_ENUM:
            interval_ratio = 2.0f;
            break;
        default:
            interval_ratio = 1.0f;
            break;
    }
    
    return base_freq * interval_ratio;
}

/* -------------------------------------------- 音乐测试函数 -------------------------------------------- */

/**
 * @brief       测试音阶
 * @param       无
 * @retval      无
 * @note        播放C大调音阶，从低音到高音
 */
void beep_music_test_scale(void)
{
    const music_note_t c_major_scale[] = {
        {NOTE_C4, 400}, {NOTE_D4, 400}, {NOTE_E4, 400}, {NOTE_F4, 400},
        {NOTE_G4, 400}, {NOTE_A4, 400}, {NOTE_B4, 400}, {NOTE_C5, 800}
    };
    
    printf("\n=== C大调音阶测试 ===\n");
    printf("播放: Do Re Mi Fa Sol La Si Do\n");
    
    beep_play_melody(c_major_scale, 8);
    
    printf("音阶测试完成！\n");
}

/**
 * @brief       测试和弦
 * @param       无
 * @retval      无
 * @note        播放C大三和弦 (C-E-G)
 */
void beep_music_test_chord(void)
{
    const music_note_t c_major_chord[] = {
        {NOTE_C4, 1000}, {NOTE_E4, 1000}, {NOTE_G4, 1000}
    };
    
    printf("\n=== C大三和弦测试 ===\n");
    printf("播放: Do Mi Sol (同时播放)\n");
    
    /* 注意：这里简化处理，实际和弦应该同时播放 */
    beep_play_melody(c_major_chord, 3);
    
    printf("和弦测试完成！\n");
}

/**
 * @brief       测试音程
 * @param       无
 * @retval      无
 * @note        播放各种音程关系
 */
void beep_music_test_interval(void)
{
    float base_freq = NOTE_C4;
    float interval_freq;
    
    printf("\n=== 音程测试 ===\n");
    
    /* 测试纯五度 */
    printf("测试纯五度: C4 -> G4\n");
    interval_freq = beep_calculate_interval(base_freq, INTERVAL_PERFECT_FIFTH_ENUM);
    beep_play_note(base_freq, 500);
    HAL_Delay(200);
    beep_play_note(interval_freq, 500);
    HAL_Delay(1000);
    
    /* 测试大三度 */
    printf("测试大三度: C4 -> E4\n");
    interval_freq = beep_calculate_interval(base_freq, INTERVAL_MAJOR_THIRD_ENUM);
    beep_play_note(base_freq, 500);
    HAL_Delay(200);
    beep_play_note(interval_freq, 500);
    HAL_Delay(1000);
    
    /* 测试八度 */
    printf("测试八度: C4 -> C5\n");
    interval_freq = beep_calculate_interval(base_freq, INTERVAL_OCTAVE_8VA_ENUM);
    beep_play_note(base_freq, 500);
    HAL_Delay(200);
    beep_play_note(interval_freq, 500);
    
    printf("音程测试完成！\n");
} 

